﻿using System.Linq;
using fleXdoc.Api;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Threading;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System.Collections.Generic;
using DocumentFormat.OpenXml.Drawing;
using System;
using System.Globalization;

namespace fleXdoc.Api.UnitTest
{
    /// <summary>
    ///This is a test class for DocBuilderTest and is intended
    ///to contain all DocBuilderTest Unit Tests
    ///</summary>
    [TestClass()]
    [DeploymentItem("data.xml")]
    [DeploymentItem("ImportTemplateTest.docx")]
    [DeploymentItem("ImportTemplateTest_absoluteDataPathNoResult.docx")]
    [DeploymentItem("ImportTemplateTest_ResolveBookmarkIDs.docx")]
    [DeploymentItem("SubDoc.docx")]
    public class DocBuilderTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        [TestMethod()]
        public void ImportTemplateTest()
        {
            // Build the document
            Stream template = IOHelper.GetFile("ImportTemplateTest.docx", FileMode.Open, FileAccess.Read, FileShare.Read);
            MemoryStream doc = new MemoryStream();

            using (DocBuilder target = new DocBuilder(template))
            {
                using (Stream data = IOHelper.GetFile("data.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    string nsPrefix = "d";
                    string ns = "http://dataschemes.com/data";
                    target.Build(data, nsPrefix, ns, (Stream)doc, CultureInfo.CurrentCulture, true);
                }
            }
            // Basic checks
            Assert.AreNotEqual(0, doc.Length, "No data");

            // Write the outputfile to disk (for manual inspection)
            using (Stream fileOutput = File.Open("ImportTemplateTest.Output.docx", FileMode.Create, FileAccess.ReadWrite))
            {
                IOHelper.CopyStream(doc, fileOutput);
                fileOutput.Flush();
                fileOutput.Close();
            }

            // Check the document
            using (WordprocessingDocument docOutput = WordprocessingDocument.Open(doc, false))
            {
                Assert.AreEqual(0, docOutput.MainDocumentPart.Document.Descendants<CustomXmlRun>().Count(), "CustomXmlRuns were found, while they should have been transformed");
                Assert.AreEqual(0, docOutput.MainDocumentPart.Document.Descendants<CustomXmlBlock>().Count(), "CustomXmlBlocks were found, while they should have been transformed");
                Assert.IsTrue(docOutput.MainDocumentPart.Document.Body.InnerText.Contains("This content originates from SubDoc.docx"), "Content from SubDoc.docx not found");

                // Check if images in subdoc have been correctly imported
                List<string> relIds = new List<string>();
                IEnumerable<Drawing> drawings = docOutput.MainDocumentPart.Document.Descendants<Drawing>();
                foreach (Drawing drawing in drawings)
                {
                    if (drawing.Inline != null && drawing.Inline.Graphic != null)
                    {
                        Blip blip = drawing.Inline.Graphic.Descendants<Blip>().FirstOrDefault();
                        if ((blip != null) && (!String.IsNullOrEmpty(blip.Embed)))
                        {
                            relIds.Add(blip.Embed);
                        }
                    }
                }
                foreach (string relId in relIds)
                {
                    OpenXmlPart part = docOutput.MainDocumentPart.GetPartById(relId);
                    Assert.IsNotNull(part, "One or more of the related parts does not exist");
                    Assert.AreEqual(typeof(ImagePart), part.GetType(), "Imageparts of imported template do not seem to be (correctly) imported: related part exists but is of wrong type");
                }
            }
        }

        [TestMethod()]
        public void ImportTemplateTest_AbsoluteDataPathNoResults()
        {
            // Build the document
            Stream template = IOHelper.GetFile("ImportTemplateTest_absoluteDataPathNoResult.docx", FileMode.Open, FileAccess.Read, FileShare.Read);
            MemoryStream doc = new MemoryStream();

            using (DocBuilder target = new DocBuilder(template))
            {
                using (Stream data = IOHelper.GetFile("data.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    string nsPrefix = "d";
                    string ns = "http://dataschemes.com/data";
                    target.Build(data, nsPrefix, ns, (Stream)doc, CultureInfo.CurrentCulture, true);
                }
            }
            // Basic checks
            Assert.AreNotEqual(0, doc.Length, "No data");

            // Write the outputfile to disk (for manual inspection)
            using (Stream fileOutput = File.Open("ImportTemplateTest_absoluteDataPathNoResult.Output.docx", FileMode.Create, FileAccess.ReadWrite))
            {
                IOHelper.CopyStream(doc, fileOutput);
                fileOutput.Flush();
                fileOutput.Close();
            }

            // Check the document
            using (WordprocessingDocument docOutput = WordprocessingDocument.Open(doc, false))
            {
                Assert.AreEqual(0, docOutput.MainDocumentPart.Document.Descendants<CustomXmlRun>().Count(), "CustomXmlRuns were found, while they should have been transformed");
                Assert.AreEqual(0, docOutput.MainDocumentPart.Document.Descendants<CustomXmlBlock>().Count(), "CustomXmlBlocks were found, while they should have been transformed");
                Assert.IsTrue(docOutput.MainDocumentPart.Document.Body.InnerText.Contains("This content originates from SubDoc.docx"), "Content from SubDoc.docx not found");
            }
        }

        [TestMethod()]
        public void ImportTemplateTest_ResolveBookmarkIDs()
        {
            // Build the document
            Stream template = IOHelper.GetFile("ImportTemplateTest_ResolveBookmarkIDs.docx", FileMode.Open, FileAccess.Read, FileShare.Read);
            MemoryStream doc = new MemoryStream();

            using (DocBuilder target = new DocBuilder(template))
            {
                using (Stream data = IOHelper.GetFile("data.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    string nsPrefix = "d";
                    string ns = "http://dataschemes.com/data";
                    target.Build(data, nsPrefix, ns, (Stream)doc, CultureInfo.CurrentCulture, true);
                    // Validation is enabled: if bookmark IDs are not correctly resolved, validation failes.
                    // So if no errors occur here, bookmark IDs are obviously correctly resolved! :)
                }
            }

            // Basic checks
            Assert.AreNotEqual(0, doc.Length, "No data");

            // Write the outputfile to disk (for manual inspection)
            using (Stream fileOutput = File.Open("ImportTemplateTest_ResolveBookmarkIDs.Output.docx", FileMode.Create, FileAccess.ReadWrite))
            {
                IOHelper.CopyStream(doc, fileOutput);
                fileOutput.Flush();
                fileOutput.Close();
            }

            // Check the document
            using (WordprocessingDocument docOutput = WordprocessingDocument.Open(doc, false))
            {
                Assert.AreEqual(0, docOutput.MainDocumentPart.Document.Descendants<CustomXmlRun>().Count(), "CustomXmlRuns were found, while they should have been transformed");
                Assert.AreEqual(0, docOutput.MainDocumentPart.Document.Descendants<CustomXmlBlock>().Count(), "CustomXmlBlocks were found, while they should have been transformed");
                Assert.IsTrue(docOutput.MainDocumentPart.Document.Body.InnerText.Contains("This content originates from SubDoc.docx"), "Content from SubDoc.docx not found");
            }
        }
    }
}